/**
 * <pre>
   Copyright 2016 aaron.sd

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 * </pre>
 * 
 * @author aaronwong.sd@foxmail.com
 * @version 下午10:06:24
 */
package com.iwechat.mp.service.task;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.iwechat.interfaces.Schedulable;
import com.iwechat.mp.service.WxmpApi;
import com.iwechat.mpapi.Configuration;
import com.iwechat.mpapi.http.OAuth;
import com.iwechat.mpapi.http.OAuthToken;
import com.iwechat.mybatis.generator.dao.WxmpAccessTokenMapper;
import com.iwechat.mybatis.generator.model.WxmpAccessToken;

/**
 * 微信公众号token管理
 * 
 * @author aaronwong.sd@foxmail.com
 */
@Service("tokenManager")
public class WxmpTokenManager implements Schedulable {
    public static final WxmpApi api          = WxmpApi.getAPI();
    private static final Logger LOG          = LoggerFactory.getLogger(WxmpTokenManager.class);
    private static final long   initialDelay = 1 * 1000;
    private static final long   fixedDelay   = 5 * 60 * 1000;

    /** 公众号Token对象 */
    private static OAuthToken   oAuthToken;
    /** 公众号对象 */
    private static OAuth        auth;

    @Autowired
    WxmpAccessTokenMapper       tokenMapper;

    /**
     * 5min调度一次
     */
    @Scheduled(initialDelay = initialDelay, fixedDelay = fixedDelay)
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void run() {
        String appId = Configuration.getOAuthAppId();
        String secret = Configuration.getOAuthSecret();
        auth = new OAuth(appId, secret);
        // lock
        tokenMapper.lock();
        // 从数据库获取token
        WxmpAccessToken token = tokenMapper.queryToken(appId);
        OAuthToken otmp = new OAuthToken();
        otmp.setAccess_token(token.getAccessToken());
        otmp.setExpires_in(token.getExpiresIn(), token.getCreateTime().getTime());
        // 判断token是否过期
        if (otmp.isExprexpired()) {
            try {
                otmp = null;
                // 从腾讯重新获取token
                otmp = api.login(appId, secret);
                if (otmp != null && otmp.getAccess_token() != null && otmp.getAccess_token().length() > 0) {
                    // 更新token到数据库
                    token.setAccessToken(otmp.getAccess_token());
                    // 预留足够的操作时间,以及为了保证token都是有效的,有效期减去2个调度间隔（5分钟调度一次）
                    // token过期两个调度时间前我们就判定其为过期
                    token.setExpiresIn(otmp.getExpires_in() - (int) (2 * fixedDelay / 1000));
                    token.setCreateTime(new Date());
                    // 更新token到数据库
                    tokenMapper.updateToken(token);
                }

            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
            }
        }
        oAuthToken = otmp;
    }

    /**
     * @return the oAuthToken
     */
    public static OAuthToken getoAuthToken() {
        return oAuthToken;
    }

    /**
     * @return the auth
     */
    public static OAuth getAuth() {
        return auth;
    }

}
